package com.express.gateway.verticle;

import com.express.gateway.common.CommonCons;
import com.express.gateway.common.EventBusTopicConst;
import com.express.gateway.common.GatewayAttribute;
import com.express.gateway.common.util.StrUtil;
import com.express.gateway.manage.entity.Api;
import com.express.gateway.manage.entity.TrackInfo;
import com.express.gateway.manage.enums.ApiServerTypeEnum;
import com.express.gateway.manage.enums.HttpMethodEnum;
import com.express.gateway.manage.options.*;
import com.express.gateway.spi.auth.Auth;
import com.express.gateway.spi.auth.AuthFactory;
import com.express.gateway.spi.auth.AuthOptions;
import com.express.gateway.spi.check.LimitCheckHandler;
import com.express.gateway.spi.check.ParamCheckHandler;
import com.express.gateway.spi.proxy.custom.CustomHandlerFactory;
import com.express.gateway.spi.proxy.custom.CustomHandlerOptions;
import com.express.gateway.spi.proxy.custom.CustomProxyHandler;
import com.express.gateway.spi.proxy.network.HttpProxyServiceHandler;
import com.express.gateway.spi.proxy.redirect.RedirectProxyRouteHandler;
import com.express.gateway.spi.round.*;
import io.vertx.core.*;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.PemKeyCertOptions;
import io.vertx.core.net.PfxOptions;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.SessionHandler;
import io.vertx.ext.web.sstore.ClusteredSessionStore;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.ext.web.sstore.SessionStore;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.MalformedURLException;
import java.util.*;

import static com.express.gateway.common.CommonCons.KEY_CLUSTER;
import static com.express.gateway.manage.enums.ApiServerTypeEnum.HTTP_HTTPS;
import static com.express.gateway.manage.enums.ApiServerTypeEnum.REDIRECT;

/**
 * Api网关配置信息
 *
 * @author flower
 */
public class AppExecuteVerticle extends AbstractVerticle {
    private static final Logger LOG = LogManager.getLogger(AppExecuteVerticle.class);
    /**
     * HTTP服务器route集
     */
    private final Map<String, List<Route>> httpRouteMaps = new LinkedHashMap<>();
    /**
     * HTTPS服务器route集
     */
    private final Map<String, List<Route>> httpsRouteMaps = new LinkedHashMap<>();
    /**
     * 全局IP黑名单
     */
    private LinkedHashSet<String> blackIpSet = new LinkedHashSet<>();
    /**
     * HTTP的路由服务
     */
    private Router httpRouter = null;
    /**
     * HTTPS的路由服务
     */
    private Router httpsRouter = null;
    /**
     * http客户端
     */
    private HttpClient httpClient = null;
    /**
     * 应用的配置信息
     */
    ApplicationOptions appOption = null;
    /**
     * 应用的名字
     */
    private String appName = null;
    /**
     * 应用的服务器与端口配置信息
     */
    ServerOptions serverOptions = null;
    /**
     * 跨域设置
     */
    CorsOptions corsOptions = null;

    /**
     * 当前Vertx的唯一标识
     */

    @Override
    public void start(Promise<Void> promise) throws Exception {
        LOG.info("load app config");
        this.appOption = new ApplicationOptions(config().getJsonObject("appConfig"));
        this.appName = appOption.getAppName();
        this.serverOptions = appOption.getServerOptions();
        LOG.info("load all blacks");
        config().getJsonArray("blackIpSet").forEach(ip -> {
            this.blackIpSet.add(ip.toString());
        });
        LOG.info("load cos config");
        this.corsOptions = appOption.getCorsOptions();
        this.httpClient = vertx.createHttpClient(appOption);

        // 注册操作地址
        Future<Void> eventBus = Future.future(future -> {
            String appName = appOption.getAppName();
            vertx.eventBus().consumer(appName + EventBusTopicConst.APPLICATION_ADD_API_SUFFIX, this::addRoute);
            vertx.eventBus().consumer(appName + EventBusTopicConst.APPLICATION_DEL_API_SUFFIX, this::delRoute);
            vertx.eventBus().consumer(KEY_CLUSTER + EventBusTopicConst.SYSTEM_PUBLISH_BLACK_IP_LIST, this::updateBlackIpAddressList);
            future.complete();
        });

        builderProxyServer(promise, eventBus);
    }

    private void builderProxyServer(Promise<Void> promise, Future<Void> eventBus) {
        List<Future<Void>> futures = new ArrayList<>(3);
        futures.add(eventBus);
        if (serverOptions.isCreateHttp()) {
            Future<Void> httpFuture = Future.future(future -> {
                createHttpServer(res -> {
                    LOG.warn("创建应用:{}, HTTP:{} 结果={}", appName, serverOptions.getHttpPort(), !res.failed(), res.cause());
                    if (res.failed()) {
                        future.fail(res.cause());
                        return;
                    }
                    future.complete();
                });
            });
            futures.add(httpFuture);
        }
        if (serverOptions.isCreateHttps()) {
            Future<Void> httpsFuture = Future.future(future -> {
                createHttpsServer(res -> {
                    LOG.warn("创建应用:{}, HTTPS:{} 服务器, 结果={}", appName, serverOptions.getHttpsPort(), !res.failed(), res.cause());
                    if (res.failed()) {
                        future.fail(res.cause());
                        return;
                    }
                    future.complete();
                });
            });
            futures.add(httpsFuture);
        }
        Future.all(futures).onSuccess(os -> {
            promise.complete();
        }).onFailure(ex -> {
            LOG.error("实例化应用程序 失败:", ex.getCause());
            promise.fail(ex.getCause());
        });
    }

    /**
     * 创建http服务器
     */
    private void createHttpServer(Handler<AsyncResult<Void>> createHttp) {
        this.httpRouter = Router.router(vertx);
        this.httpRouter.route().handler(BodyHandler.create());
        this.httpRouter.route().handler(this::filterBlackIpAddress);
        setSessionHandler(httpRouter);
        // 跨域处理
        Optional.ofNullable(corsOptions).ifPresent(corsOptions -> setCorsHandler(httpRouter));
        // 如果在linux系统开启epoll
        if (vertx.isNativeTransportEnabled()) {
            serverOptions.setTcpFastOpen(true).setTcpCork(true).setTcpQuickAck(true).setReusePort(true);
        }
        // 404页面
        checkProxyRequestPath(httpRouter);

        // 创建http服务器
        vertx.createHttpServer(serverOptions).requestHandler(httpRouter).listen(serverOptions.getHttpPort(), res -> {
            if (res.failed()) {
                LOG.error("APP:{} , Running on port:{}, error:", appName, serverOptions.getHttpPort(), res.cause());
                createHttp.handle(Future.failedFuture(res.cause()));
                return;
            }
            LOG.info("APP:{} , Running on port:{}, by Http!", appName, serverOptions.getHttpPort());
            createHttp.handle(Future.succeededFuture());
        });
    }

    /**
     * 创建https服务器
     */
    private void createHttpsServer(Handler<AsyncResult<Void>> createHttps) {
        this.httpsRouter = Router.router(vertx);
        this.httpsRouter.route().handler(BodyHandler.create());
        this.httpsRouter.route().handler(this::filterBlackIpAddress);
        setSessionHandler(httpsRouter);
        // 跨域处理
        Optional.ofNullable(corsOptions).ifPresent(corsOptions -> setCorsHandler(httpsRouter));
        // 创建https服务器
        this.serverOptions.setSsl(true);
        CertOptions certOptions = serverOptions.getCertOptions();

        // 证书路径与证书格式检查
        vertx.fileSystem().exists(certOptions.getCertPath()).onSuccess(fileRs -> {
            checkAndCreateHttpsServ(createHttps, certOptions);
        }).onFailure(ex -> {
            LOG.error(ex.getMessage());
            createHttps.handle(Future.failedFuture("无效的证书或者错误的路径"));
            // LOG.error("执行创建https服务器 失败:无效的证书或者错误的路径:如果证书存放在conf/cert中,路径可以从cert/开始,示例:cert/XXX.XXX");
        });

    }


    private void setSessionHandler(Router router) {
        SessionStore sessionStore;
        if (vertx.isClustered()) {
            sessionStore = ClusteredSessionStore.create(vertx);
        } else {
            sessionStore = LocalSessionStore.create(vertx);
        }
        SessionHandler sessionHandler = SessionHandler.create(sessionStore);
        sessionHandler.setSessionCookieName(appOption.getSessionCookieName());
        sessionHandler.setSessionTimeout(appOption.getSessionTimeOut());
        sessionHandler.setCookieless(true);
        router.route().handler(sessionHandler);
    }


    private void setCorsHandler(Router httpRouter) {
        CorsHandler corsHandler = CorsHandler.create(corsOptions.getAllowedOrigin());
        corsHandler.allowCredentials(corsOptions.isAllowCredentials());
        corsHandler.maxAgeSeconds(corsOptions.getMaxAgeSeconds());

        Optional.ofNullable(corsOptions.getAllowedHeaders()).ifPresent(corsHandler::allowedHeaders);
        Optional.ofNullable(corsOptions.getExposedHeaders()).ifPresent(corsHandler::exposedHeaders);
        Optional.ofNullable(corsOptions.getAllowedMethods()).ifPresent(corsHandler::allowedMethods);
        httpRouter.route().handler(corsHandler);
    }


    /**
     * 证书设置
     *
     * @param createHttps
     * @param certOptions
     * @param createFuture
     */
    private void checkAndCreateHttpsServ(Handler<AsyncResult<Void>> createHttps, CertOptions certOptions) {
        boolean isPem = "pem".equalsIgnoreCase(certOptions.getCertType());
        boolean isPfx = "pfx".equalsIgnoreCase(certOptions.getCertType());
        if (!isPem && !isPfx) {
            LOG.error("Invalid file format, supported '*.pem or *.pfx'");
            createHttps.handle(Future.failedFuture("Invalid file format, supported '*.pem or *.pfx'"));
            return;
        }

        if (isPem) {
            PemKeyCertOptions pemKeyCer = new PemKeyCertOptions().setCertPath(certOptions.getCertPath()).setKeyPath(certOptions.getCertKey());
            serverOptions.setPemKeyCertOptions(pemKeyCer);
        }
        if (isPfx) {
            PfxOptions pfxKeyCer = new PfxOptions().setPath(certOptions.getCertPath()).setPassword(certOptions.getCertKey());
            serverOptions.setPfxKeyCertOptions(pfxKeyCer);
        }
        checkProxyRequestPath(httpsRouter);

        // 如果在linux系统开启epoll
        if (vertx.isNativeTransportEnabled()) {
            serverOptions.setTcpFastOpen(true).setTcpCork(true).setTcpQuickAck(true).setReusePort(true);
        }
        //创建 HTTPS 服务器
        vertx.createHttpServer(serverOptions).requestHandler(httpsRouter).listen(serverOptions.getHttpsPort(), res -> {
            createHttps.handle(res.failed() ? Future.failedFuture(res.cause()) : Future.succeededFuture());
        });
    }

    /**
     * 检查请求链接是否存在
     * 404页面
     *
     * @param httpsRouter 路由器
     */
    private void checkProxyRequestPath(Router httpsRouter) {
        httpsRouter.route().order(Integer.MAX_VALUE).handler(rct -> {
            HttpServerRequest req = rct.request();
            HttpServerResponse response = rct.response();
            LOG.warn("用户: " + req.remoteAddress().host() + " 请求的了不存的路径: " + req.method() + " :" + req.path());
            Optional.ofNullable(appOption.getNotFoundContentType()).ifPresent(t -> response.putHeader(CommonCons.CONTENT_TYPE, t));
            response.end(appOption.getNotFoundResult());
        });
    }

    /**
     * 过滤黑名单
     */
    private void filterBlackIpAddress(RoutingContext rct) {
        // 添加请求到达Exp-Inlet的数量
        vertx.eventBus().request(EventBusTopicConst.SYSTEM_PLUS_EXP_REQUEST, null);
        String host = rct.request().remoteAddress().host();
        if (!blackIpSet.contains(host)) {
            rct.next();
            return;
        }
        HttpServerResponse response = rct.response();
        Optional.ofNullable(appOption.getBlacklistIpContentType()).ifPresent(type -> {
            response.putHeader(CommonCons.CONTENT_TYPE, type);
        });
        response.setStatusCode(appOption.getBlacklistIpCode());
        if (Objects.isNull(appOption.getBlacklistIpResult())) {
            response.setStatusMessage(appOption.getBlacklistIpResult());
        } else {
            response.setStatusMessage("you can't access this service");
        }
        response.end();
    }

    /**
     * 更新ip黑名单
     */
    private void updateBlackIpAddressList(Message<JsonArray> msg) {
        if (Objects.nonNull(msg.body())) {
            this.blackIpSet = new LinkedHashSet<String>(msg.body().getList());
        } else {
            blackIpSet = new LinkedHashSet<>();
        }
    }

    /**
     * 添加一个路由
     *
     * @param msg
     */
    private void addRoute(Message<JsonObject> msg) {
        JsonObject body = msg.body().getJsonObject(CommonCons.KEY_API);
        Api api = Api.fromJson(body);
        if (Objects.isNull(api)) {
            msg.fail(1400, "API参数不能为null,请检查API DTO需要实例化的JSON编写是否正确");
            return;
        }
        // 是否代理服务器启动API到当前应用
        boolean isRemote = body.getBoolean("elseRouteToThis", false);
        // 服务器的类型1=http,2=https,3=webSocket
        // todo 这里要再看下
        String svrType = body.getJsonObject("serverEntrance").getString("serverType", ApiServerTypeEnum.REDIRECT.toString());
        if (!HTTP_HTTPS.toString().equals(svrType)) {
            return;
        }
        addLocalOrRemoteRouter(msg, api);
    }

    /**
     * 添加一个路由 到当前服务器上
     *
     * @param msg
     * @param api
     */
    private void addLocalOrRemoteRouter(Message<JsonObject> msg, Api api) {
        // 本应用添加API,既属于自己的网关应用添加API
        List<Future> routers = new ArrayList<>(2);

        // 添加HTTP服务器的路由
        if (Objects.nonNull(httpRouter)) {
            Future<Boolean> httpFuture = Future.future(rs -> initRouterHandler(api, httpRouter, httpRouteMaps, rs));
            routers.add(httpFuture);
        }


        // 添加HTTPS服务器的路由
        if (Objects.nonNull(httpsRouter)) {
            Future<Boolean> httpsFuture = Future.future(rs -> initRouterHandler(api, httpsRouter, httpsRouteMaps, rs));
            routers.add(httpsFuture);
        }

        if (routers.isEmpty()) {
            msg.fail(404, "找不到服务器可以加载API 或 不存在的服务");
            return;
        }

        CompositeFuture.all(routers).onSuccess(res -> msg.reply(1)).onFailure(ex -> {
            msg.fail(500, ex.getMessage());
            LOG.error("{}", ex.getMessage(), ex);
        });
    }

    /**
     * 通用给Router添加route
     *
     * @param api       配置信息
     * @param router    要添加的router
     * @param routeMaps 要添加的route集合
     * @param result    结果
     */
    private void initRouterHandler(Api api, Router router, Map<String, List<Route>> routeMaps, Handler<AsyncResult<Boolean>> result) {
        vertx.executeBlocking(fut -> {
            List<Route> routes = new ArrayList<>();// 存储部署的路由
            // 流量限制处理器
            if (Objects.nonNull(api.getLimitUnit()) && !initApiLimitHandler(api, router, routes, fut)) {
                return;
            }
            // 参数检查的的route;
            if (!initParamCheck(api, router, routes, fut)) {
                return;
            }
            // 认证处理器
            if (Objects.nonNull(api.getAuthOptions()) && !initAuthHandler(api, router, routes, fut)) {
                return;
            }
            // 前置处理器
            if (Objects.nonNull(api.getBeforeHandlerOptions()) && !initBeforeHandler(api, router, routes, fut)) {
                return;
            }
            // 检查是否有后置处理器,有next给后置处理器,如果没有则response
            boolean isAfterHandler = api.getAfterHandlerOptions() != null;
            // S004-添加与后台交互的中心处理器
            if (!initProxyServerHandler(api, router, routes, fut)) {
                return;
            }
            // 后置处理器
            if (isAfterHandler && initAfterHandler(api, router, routes, fut)) {
                return;
            }
            // 添加异常处理器
            if (!initExceptionHandler(api, router, routes, fut)) {
                return;
            }
            routeMaps.put(api.getApiName(), routes);
            fut.complete();
            LOG.debug("启动:" + appName + ", 接口名称:" + api.getApiName() + ", URL:" + api.getPath() + "  成功：");
        }, result);
    }

    /**
     * 初始化权限认证
     *
     * @param api API信息
     * @throws Exception
     */
    private boolean initAuthHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {

        Route route = router.route();// 权限认证的route;
        try {
            processRouterSetting(api, route);
            // 添加handler
            AuthOptions authOptions = api.getAuthOptions();
            Auth authHandler = AuthFactory.getUserAuth(authOptions.getInFactoryName(), authOptions.getOption(), api, httpClient);
            route.handler(authHandler);
            routes.add(route);
            return true;
        } catch (Exception e) {
            route.remove();
            routes.forEach(Route::remove);// 清空已经成功的路由
            LOG.error(appName + ":API:" + api.getApiName() + "添加权限认证 失败:" + e);
            promise.fail(e);
            return false;
        }
    }

    /**
     * 初始化前置路由器
     *
     * @param api
     * @param router
     * @param routes
     * @param promise
     * @return
     */
    public boolean initBeforeHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {
        Route route = router.route();// 前置处理器的route;
        try {
            processRouterSetting(api, route);
            // 添加handler
            BeforeHandlerOptions options = api.getBeforeHandlerOptions();
            BeforeHandler beforeHandler = BeforeHandlerFactory.getBeforeHandler(options.getInFactoryName(), options.getOption(), api, httpClient);
            route.handler(beforeHandler);
            routes.add(route);
            return true;
        } catch (Exception e) {
            LOG.error(appName + ":API:" + api.getApiName() + "添加前置处理器 失败:" + e);
            route.remove();
            routes.forEach(Route::remove);// 清空已经成功的路由
            promise.fail(e);
            return false;
        }
    }

    /**
     * 初始化后置路由器
     *
     * @param api
     * @param router
     * @param routes
     * @param promise
     * @return
     */
    public boolean initAfterHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {
        Route route = router.route();// 前置处理器的route;
        try {
            processRouterSetting(api, route);
            // 添加handler
            AfterHandlerOptions options = api.getAfterHandlerOptions();
            AfterHandler afterHandler = AfterHandlerFactory.getAfterHandler(options.getInFactoryName(), options.getOption(), api, httpClient);
            route.handler(afterHandler);
            routes.add(route);
            return true;
        } catch (Exception e) {
            LOG.error(appName + ":API:" + api.getApiName() + "添加后置处理器 失败:" + e);
            route.remove();
            routes.forEach(Route::remove);// 清空已经成功的路由
            promise.fail(e);
            return false;
        }
    }

    /**
     * 初始化流量限制
     *
     * @param api
     * @param router
     * @param routes
     * @param promise
     * @return
     */
    public boolean initApiLimitHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {
        if (Objects.isNull(router) || Objects.isNull(api) || Objects.isNull(routes)) {
            LOG.error("参数为空！");
            promise.fail("参数为空！");
            return false;
        }

        Route route = router.route();// 流量限制的route;
        routes.add(route);
        processRouterSetting(api, route);
        if (Objects.nonNull(api.getLimitUnit())) {
            if (api.getApiLimit() <= -1 && api.getIpLimit() <= -1) {
                api.setLimitUnit(null);
            }
        }
        // 流量限制处理处理器
        LimitCheckHandler limitCheckHandler = LimitCheckHandler.create(api);
        route.handler(limitCheckHandler);
        return true;
    }

    /**
     * 初始化参数检查,参数检查已经交给处理器做了
     *
     * @param api
     * @param router
     * @param routes
     * @param promise
     * @return
     */
    public boolean initParamCheck(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {
        Route route = router.route();// 参数检查的的route;
        try {
            processRouterSetting(api, route);
            ParamCheckHandler paramCheckHandler = ParamCheckHandler.create(api, appOption.getContentLength());
            route.handler(paramCheckHandler);
            routes.add(route);
            return true;
        } catch (Exception e) {
            route.remove();
            routes.forEach(Route::remove);// 清空已经成功的路由
            LOG.error(appName + ":API:" + api.getApiName() + "添加参数检查 失败:" + e);
            promise.fail(e);
            return false;
        }
    }

    /**
     * 初始化与后端服务交互
     * isNext 下一步还是结束(也就是说如有后置处理器inNext=true,反则false)
     *
     * @param api
     * @param router
     * @param routes
     * @param promise
     * @return
     */
    public boolean initProxyServerHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promise) {
        Route route = router.route();
        boolean isNext = Objects.nonNull(api.getAfterHandlerOptions());
        try {
            routes.add(route);
            processRouterSetting(api, route);
            ApiServerTypeEnum type = api.getServerEntrance().getServerType();
            if (HTTP_HTTPS == type) {
                builderHttpProxy(isNext, api, route);
            } else if (REDIRECT == type) {
                builderRedirectProxy(isNext, api, route);
            } else {
                builderCustomProxy(isNext, api, route);
            }
        } catch (Exception e) {
            LOG.error(appName + ":API:" + api.getApiName() + "添加服务处理器 失败:" + e);
            route.remove();
            routes.forEach(Route::remove);// 清空已经成功的路由
            promise.fail(e);
            return false;
        }
        route.handler(rct -> {
            // TODO 当没有响应服务时next或者结束请求
            if (isNext) {
                rct.next();
            } else {
                rct.response().putHeader(CommonCons.SERVER, GatewayAttribute.FULL_NAME).putHeader(CommonCons.CONTENT_TYPE, api.getContentType()).setStatusCode(404).end();
            }
        });
        return true;
    }

    /**
     * 初始化异常Handler
     *
     * @param api
     * @param router
     * @param routes
     * @param promis
     * @return
     */
    public boolean initExceptionHandler(Api api, Router router, List<Route> routes, Promise<Boolean> promis) {
        Route route = router.route();
        routes.add(route);
        LOG.debug("启动" + appName + ": API:" + api.getApiName() + " 成功");
        processRouterSetting(api, route);
        route.failureHandler(rct -> {
            rct.response()
                    .putHeader(CommonCons.SERVER, GatewayAttribute.FULL_NAME)
                    .putHeader(CommonCons.CONTENT_TYPE, api.getContentType())
                    .setStatusCode(api.getResult().getFailureStatus())
                    .end(api.getResult().getFailureExample());
            TrackInfo info = new TrackInfo(appName, api.getApiName());
            if (Objects.nonNull(rct.failure())) {
                info.setErrMsg(rct.failure().getMessage());
                info.setErrStackTrace(rct.failure().getStackTrace());
                return;
            }
            info.setErrMsg("没有进一步信息 failure 为 null");
            vertx.eventBus().request(EventBusTopicConst.SYSTEM_PLUS_ERROR, info.toJson());
        });
        return true;
    }

    private static void processRouterSetting(Api api, Route route) {
        route.path(api.getPath());
        if (!Objects.equals(api.getMethod(), HttpMethodEnum.ALL)) {
            route.method(HttpMethod.valueOf(api.getMethod().getVal()));
        }
        if (Objects.nonNull(api.getConsumes())) {
            api.getConsumes().forEach(route::consumes);
        }
    }

    /**
     * 自定义服务类型处理器
     *
     * @param isNext
     * @param api
     * @param route
     * @throws Exception
     */
    private void builderCustomProxy(boolean isNext, Api api, Route route) throws Exception {
        JsonObject body = api.getServerEntrance().getBody();
        CustomHandlerOptions options = CustomHandlerOptions.fromJson(body);
        if (options == null) {
            throw new NullPointerException("自定义服务类型的配置文件无法装换为服务类");
        }
        if (body.getValue("isNext") == null) {
            body.put("isNext", isNext);
        }
        options.setOption(body);
        CustomProxyHandler customProxyHandler = CustomHandlerFactory.getCustomHandler(options.getInFactoryName(), options.getOption(), api, httpClient);
        route.handler(customProxyHandler);
    }

    /**
     * 页面跳转服务类型处理器
     *
     * @param isNext
     * @param api
     * @param route
     * @throws NullPointerException
     */
    private void builderRedirectProxy(boolean isNext, Api api, Route route) throws NullPointerException {
        RedirectProxyRouteHandler redirectTypeHandler = RedirectProxyRouteHandler.create(isNext, api);
        route.handler(redirectTypeHandler);
    }

    /**
     * HTTP/HTTPS服务类型处理器
     *
     * @param isNext
     * @param api
     * @param route
     * @throws NullPointerException
     * @throws MalformedURLException
     */
    private void builderHttpProxy(boolean isNext, Api api, Route route) throws NullPointerException, MalformedURLException {
        HttpProxyServiceHandler httpProxyHandler = HttpProxyServiceHandler.create(appName, isNext, api, httpClient);
        route.handler(httpProxyHandler);
    }


    /**
     * 更新一个路由
     *
     * @param msg
     */
    public void updateRoute(Message<JsonObject> msg) {
        if (msg.body() == null) {
            msg.fail(1400, "参数不能为空");
            return;
        }
        Api api = Api.fromJson(msg.body());
        if (api == null) {
            msg.fail(1405, "参数不能为空");
            return;
        }
        String apiName = api.getApiName();
        if (httpRouteMaps.get(apiName) != null) {
            httpRouteMaps.get(apiName).forEach(r -> r.disable().remove());
        }
        if (httpsRouteMaps.get(apiName) != null) {
            httpsRouteMaps.get(apiName).forEach(r -> r.disable().remove());
        }
        addRoute(msg);
    }

    /**
     * 删除一个路由
     *
     * @param msg
     */
    public void delRoute(Message<String> msg) {
        if (StrUtil.isNullOrEmpty(msg.body())) {
            msg.fail(1400, "参数:API名字不能为空");
            return;
        }
        String apiName = msg.body();
        if (httpRouteMaps.get(apiName) != null) {
            httpRouteMaps.get(apiName).forEach(r -> r.disable().remove());
        }
        if (httpsRouteMaps.get(apiName) != null) {
            httpsRouteMaps.get(apiName).forEach(r -> r.disable().remove());
        }
        msg.reply(1);
    }

}